home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / TABLES / MTABLE / CBTABLE.PAS < prev    next >
Pascal/Delphi Source File  |  1994-04-01  |  15KB  |  650 lines

  1. unit CBTable;
  2.  
  3. interface
  4.  
  5. uses
  6.   WinTypes,
  7.   WinProcs,
  8.   WinDos,
  9.   Strings,
  10.   MLBTypes,
  11.   Table,
  12.   WTools,
  13.   CodeBase;
  14.  
  15. const
  16.   TableDefinition: pChar = 'TABLEDEFINITION';
  17.  
  18.   t4num_str   =  'n';
  19.   t4num_doub  =  'F';
  20.   t4num_bcd   =  'N';
  21.   t4date_doub =  'D';
  22.   t4date_str  =  'd';
  23.   t4str       =  'C';
  24.   t4log       =  'L';
  25.  
  26. { TABLEDEFINITION ---------------------------------------------------
  27.      User defined resource containing information on CodeBase
  28.      table fields.
  29.      Resource structure:
  30.  
  31.      BEGIN
  32.        N, COMMENT
  33.        NAME_1, TYPE_1, LENGHT_1, DECIMALS_1,
  34.        NAME_2, TYPE_2, LENGHT_2, DECIMALS_2,
  35.        ...
  36.        NAME_N, TYPE_N, LENGHT_N, DECIMALS_N
  37.      END
  38.  
  39.      N           - INTEGER,
  40.      COMMENT     - ASCIIZ,
  41.      NAME_X      - ASCIIZ,
  42.      TYPE_X      - CHAR,
  43.      LENGHT_X    - INTEGER,
  44.      DECIMALS_X  - INTEGER.
  45.  
  46.      Note, that #0 must be added to the end of each ASCIIZ string.
  47.    ------------------------------------------------------------------ }
  48.  
  49. type
  50.     tPathStr = array [0..fsPathName] of Char;
  51.     tResStr  = array [0..50] of Char;
  52.  
  53.     pCBTable = ^tCBTable;
  54.     tCBTable = object(tListTable)
  55.       TableOpened  : Boolean;
  56.       C4Code       : PC4CODE;
  57.       CBTData      : PD4DATA;
  58.       n_skip       : Word;
  59.       FileName     : tPathStr;
  60.       ResourceName : pChar;
  61.       constructor  Init(AnItemsList: pItemsList; AC4Code: PC4CODE; AFileName: pChar; AResName: pChar);
  62.       destructor   Done; virtual;
  63.       function     AppendTable: Longint;
  64.       function     AssignField(FieldData: PChar; FieldName: PChar): Boolean;
  65.       function     BuildTable: Integer; virtual;
  66.       function     CheckCBTableStruct: Boolean;
  67.       function     CreateNewTable: Boolean;
  68.       function     DeleteItem(ItemHandle: tItemHandle): Integer; virtual;
  69.       function     GetCBTData: PD4DATA;
  70.       function     GetField(FieldData, FieldName: PChar): Boolean;
  71.       function     GetRecordCount: Longint; virtual;
  72.       function     GetRecordField(RecNo: LongInt; Index: Word): PChar; virtual;
  73.       function     GetRecordNo: Longint; virtual;
  74.       function     GetRecordWidth: Word; virtual;
  75.       function     LocateTable(RecNo: Longint): Boolean;
  76.       function     NextRecord: Boolean; virtual;
  77.       function     OpenCBTable: Integer;
  78.       procedure    CloseCBTable;
  79.       function     SkipRecord(dwRecno: Longint): Boolean; virtual;
  80.       function     SwitchFileName(NewFileName: pChar): Integer;
  81.       procedure    UnlockTable;
  82.     end;
  83.  
  84. function MessageBoxEx(HWindow: HWnd; IDS_Text, IDS_Title: Word; Style: Word): Integer;
  85.  
  86. {$I CBTABLE.INC}
  87. {$R CBTABLE.RES}
  88.  
  89. implementation
  90.  
  91. constructor tCBTable.Init(AnItemsList: pItemsList; AC4Code: PC4CODE; AFileName: pChar;
  92.                           AResName: pChar);
  93. begin
  94.   inherited Init(AnItemsList);
  95.   TableOpened := False;
  96.   StrCopy(FileName, AFileName);
  97.   ResourceName := AResName;
  98.   C4Code := AC4Code;
  99.   CBTData := nil;
  100.   n_skip := 1;
  101. end;
  102.  
  103. destructor tCBTable.Done;
  104. begin
  105.   if TableOpened then
  106.     CloseCBTable;
  107.   inherited Done;
  108. end;
  109.  
  110. function tCBTable.AppendTable: Longint;
  111. begin
  112.   AppendTable := 0;
  113.   if not TableOpened then Exit;
  114.   if d4append_blank(CBTData) = 0 then
  115.   begin
  116.     UnlockTable;
  117.     AppendTable := d4recno(CBTData);
  118.   end;
  119. end;
  120.  
  121. function tCBTable.AssignField(FieldData: PChar; FieldName: PChar): Boolean;
  122. var
  123.   FldType: Char;
  124.   Field: PF4FIELD;
  125.   D: Double;
  126.   N: LongInt;
  127.   Code: Integer;
  128.   Buff: array [0..30] of Char;
  129. begin
  130.   { Assume failure }
  131.   AssignField := False;
  132.  
  133.   if not TableOpened then
  134.     Exit;
  135.  
  136.   { Check if field exist }
  137.   Field := d4field(CBTData, FieldName);
  138.   if Field = nil then
  139.     Exit;
  140.  
  141.   { Get field type }
  142.   FldType := Char(f4type(Field));
  143.  
  144.   case FldType of
  145.     t4str:
  146.       f4assign(Field, FieldData);
  147.     t4date_doub:
  148.       begin
  149.         a4init(Buff, FieldData, 'DD/MM/YY');
  150.         f4assign(Field, Buff);
  151.       end;
  152.     t4num_bcd,
  153.     t4num_doub:
  154.       begin
  155.         if f4decimals(Field) = 0 then
  156.         begin
  157.           Val(FieldData, N, Code);
  158.           if Code <> 0 then Exit;
  159.           f4assign_long(Field, N);
  160.         end
  161.         else
  162.         begin
  163.           Val(FieldData, D, Code);
  164.           if Code <> 0 then Exit;
  165.           f4assign_double(Field, D);
  166.         end;
  167.       end;
  168.     t4log:
  169.         f4assign_char(Field, Integer(FieldData[0]));
  170.   end;
  171.  
  172.   AssignField := True;
  173.   UnlockTable;
  174. end;
  175.  
  176. function tCBTable.BuildTable: Integer;
  177. var
  178.   tResult: Integer;
  179. begin
  180.   tResult := OpenCBTable;
  181.   if tResult = tSuccess then
  182.   begin
  183.     tResult := inherited BuildTable;
  184.     UnlockTable;
  185.   end;
  186.   BuildTable := tResult;
  187. end;
  188.  
  189. function tCBTable.CheckCBTableStruct: Boolean;
  190. var
  191.   CurField: PF4FIELD;
  192.   hResInfo, hResData: THandle;
  193.   lpRes: PChar;
  194.   NoOfFields, FldDec, FldLen, i: integer;
  195.   FldType: Char;
  196.   FWD: Byte;
  197.  
  198. procedure UnlockRes;
  199. begin
  200.   (*
  201.    * Free user resource
  202.    *)
  203.   UnlockResource(hResData);
  204.   FreeResource(hResData);
  205. end;
  206.  
  207. begin
  208.   CheckCBTableStruct := False;
  209.   (*
  210.    * Load user resource with file definition
  211.    *)
  212.   hResInfo := FindResource(hInstance, ResourceName, TableDefinition);
  213.   if hResInfo = 0 then Exit;
  214.   hResData := LoadResource(hInstance, hResInfo);
  215.   lpRes := LockResource(hResData);
  216.  
  217.   (*
  218.    * Get field number
  219.    *)
  220.   NoOfFields := Integer(lpRes^);
  221.  
  222.   (*
  223.    * Check all fields in table
  224.    *)
  225.   Inc(lpRes, SizeOf(Integer) + StrLen(lpRes + SizeOf(Integer)) + SizeOf(Char));
  226.   for i := 0 to NoOfFields - 1 do
  227.   begin
  228.     (*
  229.      * Does field exist?
  230.      *)
  231.     CurField := d4field(CBTData, lpRes);
  232.     if CurField = nil then
  233.     begin
  234.       UnlockRes;
  235.       Exit;
  236.     end;
  237.     (*
  238.      * Check field type
  239.      *)
  240.     Inc(lpRes, StrLen(lpRes) + 1);
  241.     FldType := Char(lpRes^);
  242.     if FldType <> Char(f4type(CurField)) then
  243.     begin
  244.       UnlockRes;
  245.       Exit;
  246.     end;
  247.     (*
  248.      * Check field width
  249.      *)
  250.     Inc(lpRes, SizeOf(Char));
  251.     FldLen := Integer(lpRes^);
  252.     if FldLen <> f4len(CurField) then
  253.     begin
  254.       UnlockRes;
  255.       Exit;
  256.     end;
  257.     (*
  258.      * Check field decimals
  259.      *)
  260.     Inc(lpRes, SizeOf(Integer));
  261.     FldDec := Integer(lpRes^);
  262.     if FldDec <> f4decimals(CurField) then
  263.     begin
  264.       UnlockRes;
  265.       Exit;
  266.     end;
  267.     Inc(lpRes, SizeOf(Integer));
  268.   end;
  269.   (*
  270.    * Free user resource
  271.    *)
  272.   UnlockRes;
  273.   (*
  274.    * Examination passed
  275.    *)
  276.   CheckCBTableStruct := True;
  277. end;
  278.  
  279. procedure tCBTable.CloseCBTable;
  280. begin
  281.   if not TableOpened then
  282.     Exit;
  283.   d4flush_all(CBTData);
  284.   d4close(CBTData);
  285.   TableOpened := False;
  286. end;
  287.  
  288. function tCBTable.CreateNewTable: Boolean;
  289. type
  290.   TFieldInfo = array [0..0] of F4FIELD_INFO;
  291.   PFieldInfo = ^TFieldInfo;
  292. var
  293.   CBTableFields: PFieldInfo;
  294.   hResInfo, hResData, hFields: THandle;
  295.   lpRes: PChar;
  296.   NoOfFields, i: Integer;
  297. begin
  298.   CreateNewTable := False;
  299.  
  300.   (*
  301.    * Load user defined resource with file definitions
  302.    *)
  303.   hResInfo := FindResource(hInstance, ResourceName, TableDefinition);
  304.   if hResInfo = 0 then Exit;
  305.   hResData := LoadResource(hInstance, hResInfo);
  306.   lpRes := LockResource(hResData);
  307.  
  308.   (*
  309.    * Allocate memory for CodeBase file definition table
  310.    *)
  311.   NoOfFields := Integer(lpRes^);
  312.   hFields := GlobalAlloc(GMEM_MOVEABLE or GMEM_ZEROINIT, Longint((NoOfFields + 1) * SizeOf(F4FIELD_INFO)));
  313.   CBTableFields := PFieldInfo(GlobalLock(hFields));
  314.  
  315.   (*
  316.    * Fill CodeBase file definition table
  317.    *)
  318.   Inc(lpRes, SizeOf(Integer) + StrLen(lpRes + SizeOf(Integer)) + SizeOf(Char));
  319.   for i := 0 to (NoOfFields - 1) do
  320.   begin
  321.     CBTableFields^[i].fname := lpRes;
  322.     Inc(lpRes, StrLen(lpRes) + 1);
  323.     CBTableFields^[i].ftype := Char(lpRes^);
  324.     Inc(lpRes, SizeOf(Char));
  325.     CBTableFields^[i].flength := Integer(lpRes^);
  326.     Inc(lpRes, SizeOf(Integer));
  327.     CBTableFields^[i].fdecimals := Integer(lpRes^);
  328.     Inc(lpRes, SizeOf(Integer));
  329.   end;
  330.  
  331.    (*
  332.     * Create empty database
  333.     *)
  334.    CBTData := d4create(C4Code, FileName, PF4FIELD_INFO(CBTableFields), nil);
  335.  
  336.    (*
  337.     * If creation had success, close database
  338.     *)
  339.    TableOpened := CBTData <> nil;
  340.    if TableOpened then
  341.    begin
  342.      CreateNewTable := True;
  343.      d4close(CBTData);
  344.      TableOpened := False;
  345.    end;
  346.  
  347.    (*
  348.     * Free allocated memory and resource
  349.     *)
  350.    GlobalUnlock(hFields);
  351.    GlobalFree(hFields);
  352.    UnlockResource(hResData);
  353.    FreeResource(hResData);
  354. end;
  355.  
  356. function tCBTable.DeleteItem(ItemHandle: tItemHandle): Integer;
  357. var
  358.   RecNo : longint;
  359.   nRc   : Integer;
  360. begin
  361.   DeleteItem := -1;
  362.   RecNo := -1;
  363.   RecNo := GetItemRecNo(ItemHandle);
  364.   if RecNo < 0 then Exit;
  365.   if LocateTable(RecNo) then
  366.   begin
  367.     d4delete(CBTData);
  368.     DeleteItem := inherited DeleteItem(ItemHandle);
  369.   end;
  370. end;
  371.  
  372. function tCBTable.GetCBTData: PD4DATA;
  373. begin
  374.   if not TableOpened then
  375.     GetCBTData := nil
  376.   else
  377.     GetCBTData := CBTData;
  378. end;
  379.  
  380. function tCBTable.GetField(FieldData, FieldName: PChar): Boolean;
  381. var
  382.   FldType: Char;
  383.   Field: PF4FIELD;
  384. begin
  385.   { Assume failure }
  386.   GetField := False;
  387.  
  388.   if not TableOpened then
  389.     Exit;
  390.  
  391.   { Check if field exist }
  392.   Field := d4field(CBTData, FieldName);
  393.   if Field = nil then
  394.     Exit;
  395.  
  396.   { Get field type }
  397.   FldType := Char(f4type(Field));
  398.  
  399.   case FldType of
  400.     t4str:
  401.       StrCopy(FieldData, Trim(f4str(Field)));
  402.     t4date_doub:
  403.       a4format(Trim(f4str(Field)), FieldData, 'DD/MM/YY');
  404.     t4num_bcd,
  405.     t4num_doub:
  406.       begin
  407.         f4ncpy(Field, FieldData, f4len(Field));
  408.         FieldData[f4len(Field)] := #0;
  409.         Ltrim(FieldData);
  410.       end;
  411.     t4log:
  412.       begin
  413.         FieldData[0] := Char(f4char(Field));
  414.         FieldData[1] := #0;
  415.       end;
  416.   end;
  417.  
  418.   GetField := True;
  419.   UnlockTable;
  420. end;
  421.  
  422. function tCBTable.GetRecordCount: Longint;
  423. begin
  424.   if TableOpened then
  425.     GetRecordCount := d4reccount(CBTData)
  426.   else
  427.     GetRecordCount := 0;
  428. end;
  429.  
  430. function tCBTable.GetRecordField(RecNo: LongInt; Index: Word): PChar;
  431. var
  432.   PRes, ExprRes: PChar;
  433.   Res: array [0..MaxFieldWidth] of Char;
  434.   Bmp: HBitmap;
  435. begin
  436.   GetRecordField := nil;
  437.  
  438.   if not TableOpened then
  439.     Exit;
  440.  
  441.   case (ItemsList^.Items^[Index].ItemType) of
  442.     ct_String:
  443.       { String field }
  444.       begin
  445.         if ItemsList^.Items^[Index].FldName[0] = #0 then
  446.            { Get field from GetStrField }
  447.             StrCopy(Res, GetStrField(RecNo, Index))
  448.         else
  449.         begin
  450.            { Get field from database }
  451.            ExprRes := e4parse(CBTData, ItemsList^.Items^[Index].FldName);
  452.            e4vary(ExprRes, @PRes);
  453.            strcopy(Res, Trim(PRes));
  454.            e4free(ExprRes);
  455.         end;
  456.       end;
  457.     ct_Bitmap:
  458.       { Bitmap field }
  459.       begin
  460.          { Get Bitmap from GetBmpField }
  461.         Bmp := GetBmpField(RecNo, Index);
  462.         move(Bmp, Res, SizeOf(HBitmap));
  463.       end;
  464.   end;
  465.  
  466.   GetRecordField := Res;
  467. end;
  468.  
  469. function tCBTable.GetRecordNo: Longint;
  470. begin
  471.   if TableOpened then
  472.     GetRecordNo := d4recno(CBTData)
  473.   else
  474.     GetRecordNo := -1;
  475. end;
  476.  
  477. function tCBTable.GetRecordWidth: Word;
  478. begin
  479.   if TableOpened then
  480.     GetRecordWidth := d4record_width(CBTData)
  481.   else
  482.     GetRecordWidth := 0;
  483. end;
  484.  
  485. function TCBTable.LocateTable(RecNo: Longint): Boolean;
  486. var
  487.   nRc: Integer;
  488. begin
  489.   LocateTable := False;
  490.   repeat
  491.     nRc := d4go(CBTData, RecNo);
  492.     if nRc = r4locked then
  493.     begin
  494.       nRc := MessageBoxEx(GetFocus, ids_CBTERR_LOCK,
  495.                                     ids_CBTERROR, mb_RETRYCANCEL or mb_IconExclamation);
  496.       if nRc = idCancel then
  497.         Exit;
  498.     end
  499.     else
  500.       if nRc <> 0 then
  501.         Exit;
  502.   until nRc = 0;
  503.   LocateTable := True;
  504. end;
  505.  
  506. function tCBTable.NextRecord: Boolean;
  507. var
  508.   nRc: Integer;
  509. begin
  510.   NextRecord := False;
  511.   if not TableOpened then
  512.     Exit;
  513.   NextRecord := True;
  514.   nRc := d4skip(CBTData, n_skip);
  515.   if nRc = r4locked then
  516.   begin
  517.     { Insert message that there were locked records }
  518.     repeat
  519.       nRc := MessageBoxEx(GetFocus, ids_CBTERR_LOCK,
  520.                                     ids_CBTERROR, mb_RETRYCANCEL or mb_IconExclamation);
  521.       if nRc = idCancel then
  522.       begin
  523.         MessageBoxEx(GetFocus, ids_CBTERR_LOSEINFO,
  524.                                ids_CBTERROR, mb_OK or mb_IconInformation);
  525.         Inc(n_skip);
  526.         nRc := 0;
  527.       end
  528.       else
  529.         nRc := d4skip(CBTData, n_skip);
  530.     until nRc = 0;
  531.   end
  532.   else
  533.     if nRc = r4eof then
  534.       NextRecord := False
  535.     else
  536.       n_skip := 1;
  537. end;
  538.  
  539. function tCBTable.OpenCBTable: Integer;
  540. var
  541.   HFile: File;
  542.   ExpName: tPathStr;
  543. begin
  544.   if TableOpened then
  545.     Exit;
  546.  
  547.   TableOpened := False;
  548.  
  549.   { Assume failure }
  550.   OpenCBTable := -1;
  551.  
  552.   FileSearch(ExpName, FileName, GetEnvVar('PATH'));
  553.  
  554.   if ExpName[0] = #0 then
  555.     begin
  556.       (*
  557.        * File wasn't found
  558.        *)
  559.       if (MessageBoxEx(GetFocus, ids_CBTERR_FILENOTFOUND,
  560.                                  ids_CBTERROR, mb_YESNO or mb_IconQuestion) = id_YES) then
  561.         (*
  562.          * Attempt to create new database
  563.          *)
  564.       begin
  565.         if not CreateNewTable then
  566.           begin
  567.             (*
  568.              * New database couldn't be created
  569.              *)
  570.             MessageBoxEx(GetFocus, ids_CBTERR_CREATENEW,
  571.                                    ids_CBTFERROR, mb_OK or mb_IconHand);
  572.             Exit;
  573.           end
  574.       end
  575.       else
  576.         Exit;
  577.     end
  578.   else
  579.     (*
  580.      * File found
  581.      *)
  582.     FileExpand(FileName, ExpName);
  583.  
  584.   CBTData := d4open(C4Code, FileName);
  585.  
  586.   if CBTData = nil then
  587.   begin
  588.     (*
  589.      * Open Table fails
  590.      *)
  591.     MessageBoxEx(GetFocus, ids_CBTERR_OPENFILE,
  592.                            ids_CBTFERROR, mb_OK or mb_IconHand);
  593.     Exit;
  594.   end;
  595.  
  596.   if not CheckCBTableStruct then
  597.   begin
  598.     (*
  599.      * Check structure fails
  600.      *)
  601.     MessageBoxEx(GetFocus, ids_CBTERR_STRUCT,
  602.                            ids_CBTFERROR, mb_OK or mb_IconHand);
  603.     d4close(CBTData);
  604.     Exit;
  605.   end;
  606.  
  607.   d4top(CBTData);
  608.   TableOpened := True;
  609.   OpenCBTable := tSuccess;
  610. end;
  611.  
  612. function tCBTable.SkipRecord(dwRecno: Longint): Boolean;
  613. begin
  614.   SkipRecord := True;
  615.   if not TableOpened then
  616.     Exit;
  617.   if (d4deleted(CBTData) <> 0) then
  618.   else
  619.     SkipRecord := False;
  620. end;
  621.  
  622. function tCBTable.SwitchFileName(NewFileName: pChar): Integer;
  623. begin
  624.   StrCopy(FileName, NewFileName);
  625.   n_skip := 1;
  626. end;
  627.  
  628. procedure tCBTable.UnlockTable;
  629. begin
  630.   if TableOpened then
  631.     d4unlock_all(CBTData);
  632. end;
  633.  
  634. { MessageBoxEx ------------------------------------------------------
  635.      Display message according to stringtable ids
  636.   ------------------------------------------------------------------- }
  637. function MessageBoxEx(HWindow: HWnd; IDS_Text, IDS_Title: Word; Style: Word): Integer;
  638. const
  639.   Title_Len = 50;
  640.   Text_Len  = 200;
  641. var
  642.   mb_Title : array [0..Title_Len] of Char;
  643.   mb_Text  : array [0..Text_Len] of Char;
  644. begin
  645.   LoadString(hInstance, IDS_Text, mb_Text, SizeOf(mb_Text));
  646.   LoadString(hInstance, IDS_Title, mb_Title, SizeOf(mb_Title));
  647.   MessageBoxEx := MessageBox(HWindow, mb_Text, mb_Title, Style);
  648. end;
  649.  
  650. end.